#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>
using namespace std;
#define SEP " "
#define SEP_LEN strlen(SEP)
#define SEP_LINE "\r\n"
#define SEP_LINE_LEN strlen(SEP_LINE)
//"text_len/r/text/r/n"
bool enLength(string &text)
{
    if (text.empty())
        return false;
    int len = text.size();
    string len_string = to_string(len);
    if (len_string.empty())
        return false;
    string ret;
    ret += len_string;
    ret += SEP_LINE;
    ret += text;
    ret += SEP_LINE;
    text = ret;
    return true;
}
bool deLength(const string &package, string &text)
{
    auto index = package.find(SEP_LINE);
    if (index == string::npos)
        return false;
    string len_string = package.substr(0, index);
    int len = stoi(len_string);
    text.clear();
    text = package.substr(index + SEP_LINE_LEN, len);
    return true;
}
class Request
{
public:
    Request() {}
    Request(int x, int y, char op) : _x(x), _y(y), _op(op) {}
    //"x op y"
    bool serialize(string &out)
    {
        Json::Value root;
        root["left"] = _x;
        root["right"] = _y;
        root["op"] = _op;
        Json::FastWriter writer;
        out = writer.write(root);
        return true;
    }

    bool deserialize(const string &in)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);
        _x = root["left"].asInt();
        _y = root["right"].asInt();
        _op = root["op"].asInt();
        return true;
    }

public:
    int _x;
    int _y;
    char _op;
};
class Response
{
public:
    Response() {}
    Response(int exitcode, int result) : _exitcode(exitcode), _result(result) {}
    //"exitcode result"
    bool serialize(string &out)
    {
        Json::Value root;
        root["exitcode"] = _exitcode;
        root["result"] = _result;
        Json::FastWriter writer;
        out = writer.write(root);
        return true;
    }
    bool deserialize(const string &in)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);
        _exitcode = root["exitcode"].asInt();
        _result = root["result"].asInt();
        return true;
    }

public:
    int _exitcode;
    int _result;
};

bool recvPackage(const int &fd, string &inbuffer, string &text)
{
    auto index = inbuffer.find(SEP_LINE);
    if (index == string::npos)
        return false;
    string len_string = inbuffer.substr(0, index);
    int len = stoi(len_string);
    int total = len + SEP_LINE_LEN * 2 + len_string.size();
    if (inbuffer.size() < total)
    {
        return false;
    }
    text = inbuffer.substr(0, total);
    inbuffer.erase(0, total);
    return true;
}